/**
 * StrategyChser is a generic class allowing to build the list of
 * classes of a given package that implement a precise interface
 * or that herit from a precise class. That is very useful when we want
 * to offer extensible strategies to the user, for example testing different
 * algorithms, adding his own algorithms as new strategies, etc...
 * 
 * @created 2007-04-05
 * @author adelaye
 */

package utils;

import java.io.*;
import java.util.*;

public class StrategyChoser {

    private File _dir;
    private String _package;
    private Vector<Class> _classes;

    public static final String CLASSNAME_PATTERN = "[A-Z][A-Za-z]*[.]class";

    public StrategyChoser(String package_name){
	String dir = this.getClass().getResource("..").getPath();
	String pack = package_name.replace(".",File.separator);
	_dir = new File(dir + pack);
	_classes = new Vector<Class>();
	_package = package_name;
	init();
    }


    public void init(){
	File[] files = _dir.listFiles();
	for(File f : files){
	    String name = f.getName();
	    if(!f.isDirectory() && name.matches(CLASSNAME_PATTERN)){
		name = name.substring(0,name.length()-6);
		try{
		    Class c = Class.forName(_package + "." +name);
		    _classes.add(c);
		}
		catch(Exception e){
		    System.out.println(e);
		}
	    }
	}
    }


    public void checkSuperclass(String sc){
	Vector<Class> filtered = new Vector<Class>();
	String scName = _package + "." + sc;
	for(Class c : _classes){
	    Class superclass = c.getSuperclass();
	    if(superclass!=null && superclass.getName().equals(scName)){
		filtered.add(c);
	    }
	}
	_classes = filtered;    
    }


    public void checkInterface(String inter){
	Vector<Class> filtered = new Vector<Class>();
	String iName = _package + "." + inter;
	for(Class c : _classes){
	    Class[] interfaces = c.getInterfaces();
	    for(Class interf : interfaces){
		if(interf.getName().equals(iName)){
		    filtered.add(c);
		    break;
		}
	    }
	}
	_classes = filtered;    
    }


    public Vector getStrategies(){
	return _classes;    
    }


    public static void main(String[] args){

	StrategyChoser sc = new StrategyChoser("comRadiusController");
	System.out.println("before checking for superclass ComRadiusController:");
	Vector<Class> strategies = sc.getStrategies();
	for(Class c : strategies){
	    System.out.println(c.getName());
	}

	System.out.println("after checking for superclass ComRadiusController:");
	sc.checkSuperclass("ComRadiusController");
	Vector<Class> strategies2 = sc.getStrategies();
	for(Class c : strategies2){
	    System.out.println(c.getName());
	}

	// before checking for superclass ComRadiusController:
	// comRadiusController.ComRadiusController
	// comRadiusController.MaxReachController
	// comRadiusController.ThreeNeighborsController
	// comRadiusController.VoronoiController
	// comRadiusController.Vertex

	// after checking for superclass ComRadiusController:
	// comRadiusController.MaxReachController
	// comRadiusController.ThreeNeighborsController
	// comRadiusController.VoronoiController


	StrategyChoser sc2 = new StrategyChoser("communication.thirdLayer");
	System.out.println("before checking for superclass ThirdLayerProtocol:");
	Vector<Class> strategies3 = sc2.getStrategies();
	for(Class c : strategies3){
	    System.out.println(c.getName());
	}

	System.out.println("after checking for superclass ThirdLayerProtocol:");
	sc2.checkSuperclass("ThirdLayerProtocol");
	Vector<Class> strategies4 = sc2.getStrategies();
	for(Class c : strategies4){
	    System.out.println(c.getName());
	}

	// before checking for superclass ThirdLayerProtocol:
	// communication.thirdLayer.Router
	// communication.thirdLayer.ThirdLayerManager
	// communication.thirdLayer.ThirdLayerProtocol
	// communication.thirdLayer.RoutingTableEntry
	// communication.thirdLayer.AODVProtocol
	// communication.thirdLayer.Gradient
	// communication.thirdLayer.InterestEntry
	// communication.thirdLayer.OLSRProtocol
	// communication.thirdLayer.RouterAODV
	// communication.thirdLayer.SensorRouter
	// communication.thirdLayer.SensorRouting

	// after checking for superclass ThirdLayerProtocol:
	// communication.thirdLayer.AODVProtocol
	// communication.thirdLayer.OLSRProtocol
	// communication.thirdLayer.SensorRouting
	
	StrategyChoser sc3 = new StrategyChoser("communication.frequencyChoice");
	System.out.println("before checking for interface AlgoFreqChoice:");
	Vector<Class> strategies5 = sc3.getStrategies();
	for(Class c : strategies5){
	    System.out.println(c.getName());
	}

	System.out.println("after checking for interface AlgoFreqChoice:");
	sc3.checkInterface("AlgoFreqChoice");
	Vector<Class> strategies6 = sc3.getStrategies();
	for(Class c : strategies6){
	    System.out.println(c.getName());
	}
	
	// before checking for interface AlgoFreqChoice:
	// communication.frequencyChoice.AlgoFreqChoice
	// communication.frequencyChoice.RandomFrequency

	// after checking for interface AlgoFreqChoice:
	// communication.frequencyChoice.RandomFrequency

    }
}